package edu.muohio.cse385.drawsomething;

import java.sql.ResultSet;
import java.sql.SQLException;


public class GameInfo {
	private String		_user1;
	private String		_user2;
	private String		_state;
	private int			_player;
	private String		_word;
	private int			_value;
	
	
	/**
	 * Default constructor. Initializes object with visibly invalid values.
	 */
	private GameInfo() {
		assignInvalidValues();
	}
	
	
	/**
	 * Builds a GameInfo object representing a current game.
	 * 
	 * @param user1
	 *		username of first player
	 * @param user2
	 *		username of second player
	 * @return 
	 *		object if successful; null if game does not exist or an error occurred
	 */
	public static GameInfo getGame(String user1, String user2) {
		if (user1 == null || user2 == null || user1.isEmpty() || user2.isEmpty()) {
			return null;
		}
		
		ResultSet rsGameInfo = DatabaseConnection.executeSingleQuery(String.format(
			"SELECT * FROM game_state WHERE user1='%s' AND user2='%s'",
			user1, user2
		));
		
		if (rsGameInfo == null) {
			return null;
		}
		
		GameInfo info = new GameInfo();
		
		try {
			if (rsGameInfo.first()) {
				info._user1 = rsGameInfo.getString("user1");
				info._user2 = rsGameInfo.getString("user2");
				info._state = rsGameInfo.getString("state");
				info._player = rsGameInfo.getString("player").equals("1") ? 1 : 2;
				info._word = rsGameInfo.getString("word");
				info._value = rsGameInfo.getInt("value");
			}
			else {
				info = null;
			}
			
			rsGameInfo.close();
		}
		catch (SQLException e) {
			System.err.println(
				"ERR GameInfo.getGame: failed to get game info: " +
				e.getLocalizedMessage()
			);
			
			info = null;
		}
		finally {
			rsGameInfo = null;
		}
		
		DatabaseConnection.endConnection();
		
		return info;
	}
	
	
	/**
	 * Commits data from a GameInfo object into the database.
	 * 
	 * @param info
	 *		object representing game data
	 * @return 
	 *		true if successful; false otherwise
	 */
	public static boolean updateGame(GameInfo info) {
		if (info == null) {
			return false;
		}
		
		int result = -1;
		String updateInfoCmd = String.format(
			"UPDATE game_state SET state='%s', player='%s', word='%s', value=%d WHERE user1='%s' AND user2='%s'",
			info._state,
			info._player == 1 ? "1" : "2",
			info._word,
			info._value,
			info._user1,
			info._user2
		);
		
		return DatabaseConnection.executeSingleUpdate(updateInfoCmd) > 0 ? true : false;
	}
	
	
	/**
	 * Removes game state data from the database.
	 * 
	 * @param info
	 *		game to be removed
	 * @return 
	 *		true if successful; false if game does not exist or any other failure
	 */
	public static boolean removeGame(GameInfo info) {
		if (info == null) {
			return false;
		}
		
		// smithre5: Smart thing would be to have FK cascade and remove image data from
		// game_events, too.
		
		int result = -1;
		String updateInfoCmd = String.format(
			"DELETE FROM game_state WHERE user1='%s' AND user2='%s'",
			info._user1,
			info._user2
		);
		
		result = DatabaseConnection.executeSingleUpdate(updateInfoCmd);
		
		if (result > 0) {
			info.assignInvalidValues();
			return true;
		}
		else {
			return false;
		}
	}
	
	
	private void assignInvalidValues() {
		_user1 = "INVALID-USER";
		_user2 = "INVALID-USER";
		_state = "INVALID-STATE";
		_player = -1;
		_word = "INVALID-WORD";
		_value = -1;
	}
	
	
	public String getFirstPlayer() {
		return _user1;
	}
	
	
	public String getSecondPlayer() {
		return _user2;
	}
	
	
	public int getCurrentPlayer() {
		return _player;
	}
	
		
	public boolean setCurrentPlayer(int player) {
		if (player != 1 && player != 2) {
			return false;
		}
		
		_player = player;
		return true;
	}
		
	
	public String getState() {
		return _state;
	}
	
	
	public boolean setState(String state) {
		if (state == null || state.isEmpty()) {
			return false;
		}
		
		// Forces state advancement logic
		if (_state.equals("select") && !state.equals("draw")) {
			return false;
		}
		else if (_state.equals("draw") && !state.equals("guess")) {
			return false;
		}
		else if (_state.equals("guess") && !state.equals("select")) {
			return false;
		}
		
		return true;
	}
	
	
	public String getWord() {
		return _word;
	}
	
	
	public boolean setWord(String word) {
		// TODO Guarantee word is valid.		
		if (word == null || word.isEmpty()) {
			return false;
		}
		
		_word = word;
		return true;
	}
	
	
	public int getWordValue() {
		return _value;
	}
	
	
	public boolean setWordValue(int value) {
		if (value != 1 && value != 2 && value != 3) {
			return false;
		}
		
		_value = value;
		return true;
	}
}
